package com.todo.event.activity.application.handler.activityreward;

import com.alibaba.fastjson.JSONObject;
import com.todo.event.activity.application.entity.context.RewardSendContext;
import com.todo.event.activity.common.enums.EventActivityExecuteRewardEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author azhebuxing
 * @date 2025/1/13 20:22
 * @description
 */
@Slf4j
@Component
public class RewardFactory {

    @Autowired
    private List<AbstractRewardHandle> rewardHandleList;

    ThreadPoolExecutor rewardSendExecute = new ThreadPoolExecutor(10, 10, 5000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100));


    public AbstractRewardHandle getRewardHandle(EventActivityExecuteRewardEnum rewardEnum) {
        for (AbstractRewardHandle rewardHandle : rewardHandleList) {
            if (rewardHandle.getReward().equals(rewardEnum)) {
                return rewardHandle;
            }
        }
        return null;
    }

    public boolean handle(List<RewardSendContext> contextList) {
        if (CollectionUtils.isEmpty(contextList)) {
            return true;
        }

        List<CompletableFuture> futureList = new ArrayList<>();
        for (RewardSendContext context : contextList) {
            AbstractRewardHandle rewardHandle = getRewardHandle(context.getRewardEnum());
            CompletableFuture future = CompletableFuture.supplyAsync(() -> rewardHandle.handle(context), rewardSendExecute);
            futureList.add(future);
        }
        List<Boolean> result = new ArrayList<>();
        try {
            CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).get(5000, TimeUnit.MILLISECONDS);
            futureList.forEach(future -> {
                try {
                    Boolean sendResult = (Boolean) future.get();
                    if (Objects.nonNull(sendResult)) {
                        result.add(sendResult);
                    }
                } catch (Exception ignore) {
                }
            });
        } catch (Exception ex) {
            log.error("RewardFactory#handle 批处理奖励发放系统异常 ，contextList：【{}】", JSONObject.toJSONString(contextList), ex);
        }
        if (CollectionUtils.isNotEmpty(result)) {
            for (Boolean b : result) {
                if (!b) {
                    return false;
                }
            }
        }
        return true;
    }
}
